/**
 * 
 */
package co.fitstart.mobile.handler.impl;


import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;

import javax.annotation.Resource;

import org.apache.http.Consts;
import org.apache.http.client.fluent.Form;
import org.apache.http.client.fluent.Request;
import org.apache.http.client.fluent.Response;
import org.apache.http.entity.ContentType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.alibaba.fastjson.JSON;
import com.demo2do.core.support.Result;
import com.demo2do.core.utils.DateFormatUtils;
import com.demo2do.core.utils.JsonUtils;
import com.demo2do.core.utils.SignatureUtils;
import com.demo2do.core.utils.StringUtils;

import co.fitstart.entity.order.Order;
import co.fitstart.mobile.handler.PaymentHandler;

/**
 * @author lute
 *
 */
@Component("paymentHandler")
public class PaymentHandlerImpl implements PaymentHandler {

    private static final Logger logger = LoggerFactory.getLogger(PaymentHandlerImpl.class);
    
    @Value("#{ctx['api.host']}")
    private String apiHost;
    
    @Resource(name = "payment")
    private Properties properties;
    
    /* (non-Javadoc)
     * @see co.fitstart.mobile.handler.PaymentHandler#prepare(co.fitstart.mobile.entity.trading.PaymentPrepare)
     */
    public Result preparePay(String orderNo, String customerId, String channel, Map<String, String> parameters) {

        Result result = new Result();
        
        Map<String, String> query = new HashMap<String, String>();
        
        // Get checkout properties
        String appid = properties.getProperty("appid");
        String appsecret = properties.getProperty("appsecret");
        String checkoutHost = properties.getProperty("checkout.host");
        String checkoutPath = properties.getProperty("checkout." + channel.toLowerCase());
        
        query.put("appid", appid);
        query.put("channel", channel);
        query.put("order_no", orderNo);
        query.put("customer_id", customerId);
        query.put("app_notify_url", apiHost + "/v1/payments/callback");
        
        query.putAll(parameters);
        
        
        // Generate signature
        String sortedQueryString = StringUtils.toSortedQueryString(query) + "&appsecret=" + appsecret;
        String signature = SignatureUtils.makeMD5Signature(sortedQueryString).toUpperCase();
        query.put("signature", signature);
        
        try {
            
            // Construct form
            Form form = Form.form();
            for (Iterator<Entry<String, String>> iterator = query.entrySet().iterator(); iterator.hasNext();) {
                Entry<String, String> entry = iterator.next();
                form.add(entry.getKey(), entry.getValue());
            }
            
            Response response = Request.Post(checkoutHost + checkoutPath)
                                       .connectTimeout(30000)
                                       .socketTimeout(30000)
                                       .bodyForm(form.build(), Consts.UTF_8)
                                       .execute();
            
            String body = response.returnContent().asString(Consts.UTF_8);
            logger.trace("CheckoutHandlerImpl#prePay() - Get response body [{}].", body);
            
            result = JSON.parseObject(body, Result.class);
            
        } catch (IOException e) {
            logger.error("CheckoutHandlerImpl#prepay() - Requesting checkout counter for payment preparation euncouters IO exception: {}", e);
        }
        
        return result;
    }
    
//    public Result prepare(PaymentPrepare paymentPrepare) {
//        
//        Result result = new Result();
//        
//        Map<String, String> query = new HashMap<String, String>();
//        
//        // Get checkout properties
//        String checkoutHost = properties.getProperty("checkout.host");
//        String checkoutPath = properties.getProperty("checkout.prepare");
//        
//        query.put("channel", paymentPrepare.getChannel());
//        query.put("orderNo", paymentPrepare.getOrderNo());
//        query.put("userId",  paymentPrepare.getUserId());
//        
//        query.putAll(paymentPrepare.getExtras());
//        
//        try {
//            
//            String content = JsonUtils.toJsonString(query);
//            Response response = Request.Post(checkoutHost + checkoutPath)
//                                       .bodyString(content, ContentType.APPLICATION_JSON)
//                                       .connectTimeout(30000)
//                                       .socketTimeout(30000)
//                                       .execute();
//            
//            String body = response.returnContent().asString(Consts.UTF_8);
//            
//            logger.trace("CheckoutHandlerImpl#prePay() - Get response body [{}].", body);
//            
//            result = JSON.parseObject(body, Result.class);
//            
//        } catch (IOException e) {
//            
//            logger.error("CheckoutHandlerImpl#prepay() - Requesting checkout counter for payment preparation euncouters IO exception: {}", e);
//        
//        }
//        
//        return result;
//        
//    }

    public Result payOrder(Order order, String requestNo, String channel) {
        Result result = new Result();
        
        try {
            
            String appId = properties.getProperty("appid");
            String appsecret = properties.getProperty("appsecret");
            
            Map<String, String> parameters = new LinkedHashMap<String, String>();
            parameters.put("appid", appId);
            parameters.put("channel", channel);
            parameters.put("order_no", order.getCode());
            parameters.put("customer_id", order.getUser().getId().toString());
            parameters.put("amount", String.valueOf(order.getPayingPrice()));
            parameters.put("pay_time", DateFormatUtils.format(new Date(), "yyyyMMddHHmmss"));
            parameters.put("request_no", requestNo);
            
            String queryString = StringUtils.toSortedQueryString(parameters) + "&key=" + appsecret;
            String signature = SignatureUtils.makeMD5Signature(queryString).toUpperCase();
            
            parameters.put("signature", signature);
            String content = JsonUtils.toJsonString(parameters);
            
            Response response = Request.Post(apiHost + "/v1/payments/callback")
                                       .bodyString(content, ContentType.APPLICATION_JSON)
                                       .connectTimeout(100000)
                                       .socketTimeout(100000)
                                       .execute();
            
            String body = response.returnContent().asString(Consts.UTF_8);
            logger.trace("PaymentHandlerImpl#payOrder() - Get response body [{}].", body);
            
            result = JSON.parseObject(body, Result.class);
            
        } catch (Exception e) {
            logger.error("PaymentHandlerImpl#payOrder() - Requesting payment callback api euncouters exception: [{}]", e);
        }
        
        return result;
    }
}
